<?php
/**
 * 本类主要完成企业微信授权操作
 * Created by PhpStorm.
 * User: zd
 * Date: 2018/10/8
 * Time: 17:32
 */

namespace app\api\service;


use app\api\model\WorkAgent;
use app\api\model\Work as WorkModel;
use app\api\model\WorkDepartment;
use app\api\model\WorkUser;
use app\api\model\ThirdApp;
use app\lib\exception\WorkSuiteTicketException;
use think\Cache;
use think\Loader;
use think\Request;

Loader::import('WorkWx.callback.WXBizMsgCrypt',EXTEND_PATH);
Loader::import('WorkWx.api.src.ServiceCorpAPI',EXTEND_PATH,'.class.php');

class Work
{
    private $encodingAesKey;
    private $token;
    private $corpId;

    function __construct($encodingAesKey=null,$token = null,$copId = null)
    {
        $this->encodingAesKey = $encodingAesKey;
        $this->token = $token;
        $this->corpId = $copId;
    }
    /**
     * 验证url向企业微信返回通信标识
     * @return string
     */
    public function get(){
        $sEchoStr = "";
        $data = Request::instance()->param();
        $wxcpt = new \WXBizMsgCrypt($this->token,$this->encodingAesKey,$this->corpId);
        $errCode =  $wxcpt->VerifyURL($data['msg_signature'], $data['timestamp'], $data['nonce'], $data['echostr'],$sEchoStr);
        if ($errCode == 0) {
            return $sEchoStr;
        } else {
            return "ERR: " . $errCode . "\n\n";
        }
    }
    /**
     *接收微信平台传递消息时
     * @return mixed|string
     */
    public function getNotify(){
        $getData = Request::instance()->param();
        $postData = file_get_contents('php://input');
        $sMsg = "";  // 解析之后的明文
        $wxcpt = new \WXBizMsgCrypt($this->token,$this->encodingAesKey,$this->corpId);
        $errCode =  $wxcpt->DecryptMsg($getData['msg_signature'],$getData['timestamp'],$getData['nonce'],$postData,$sMsg);
        if ($errCode == 0) {
           $data =  $this->Xml2Array($sMsg);
            //error_log(print_r($data, 1), 3, "./user");
            $this->getInfoType($data);
            return $data;
        } else {
            return  "ERR: " . $errCode . "\n\n";
        }
    }
    /**
     * 获取预授权码
     * @param $suiteID
     * @param $Secret
     * @return mixed
     */
    public function getPreAuthCode($suiteID,$Secret){
        $vars =  Cache::get($suiteID);
        $vars = json_decode($vars);
        $suite_ticket = $vars->SuiteTicket;
        $service = new \ServiceCorpAPI($suiteID,$Secret,$suite_ticket);
        $preAuthCode = $service->GetPreAuthCode();
        return $preAuthCode;
    }
    /**
     * 构造授权链接
     * @param $suit_id
     * @param $Secret
     * @param $redirect_uri
     * @return string
     */
    public function makeAuthUrl($suit_id,$Secret,$redirect_uri,$token){
        $pre_auth_code = $this->getPreAuthCode($suit_id,$Secret);
        $url = 'https://open.work.weixin.qq.com/3rdapp/install?suite_id='.$suit_id.'&pre_auth_code='.$pre_auth_code.'&redirect_uri='.$redirect_uri.'&state='.$token;
        return $url;
    }
    /**
     * 设置授权配置
     * @param $pre_auth_code
     * @param $appid
     * @param $auth_type
     */
    public function setAppConfig($pre_auth_code,$suiteID,$Secret){
        $vars =  Cache::get($suiteID);
        $vars = json_decode($vars);
        $suite_ticket = $vars->SuiteTicket;
        //构造session_info传递参数
        $sesseion_info = new \SessionInfo();
        $sesseion_info->appid = $suiteID;
        $sesseion_info->auth_type = 1;
        //为$SetSessionInfoReq对象赋值
        $SetSessionInfoReq =  new \SetSessionInfoReq();
        $SetSessionInfoReq->pre_auth_code = $pre_auth_code;
        $SetSessionInfoReq->session_info = $sesseion_info;
        //发起应用设置
        $service = new \ServiceCorpAPI($suiteID,$Secret,$suite_ticket);
        $status = $service->SetSessionInfo($SetSessionInfoReq);
        return $status;
    }

    /**
     * 获取微信推送回调信息
     * @param $data
     * @return string
     * @throws WorkSuiteTicketException
     */
    private function getInfoType($data){
        switch ($data['InfoType']){
            case 'suite_ticket' :
                    if (!empty($data['SuiteTicket'])){
                        $this->saveToCache($data);
                    }else{
                        throw new WorkSuiteTicketException([
                            'code'=>500,
                            'msg'=>'获取suite_ticket异常'
                        ]);
                    }
                break;
            case 'create_auth';//授权成功

                break;
            case 'change_auth';//变更授权

                break;
            case 'cancel_auth';//取消授权
                if (!empty($data['InfoType'])){
                    $this->deleteApply($data);
                }
                break;
            case 'change_contact';//通讯录授权变动
                if (!empty($data['ChangeType'])){
                    $this->receiveAuthNotify($data);
                }
                break;
        }
    }
    /**
     * 获取永久授权码
     * @param $data
     * @return \GetPermanentCodeRsp
     */
    public function getPermanentCode($code,$suiteID,$Secret){
        $vars =  Cache::get($suiteID);
        $vars = json_decode($vars);
        $suite_ticket = $vars->SuiteTicket;
        $service = new \ServiceCorpAPI($suiteID,$Secret,$suite_ticket);
        //获取信息
        $PermanentCode = $service->GetPermanentCode($code);
        //缓存信息
        $access_token = $PermanentCode->access_token;//access_token
        $expires_in = $PermanentCode->expires_in;//过期时间
        $key = $PermanentCode->auth_corp_info->corpid;//永久授权码
        cache($key,json_encode($access_token),$expires_in);
        return $PermanentCode;
    }
    /**
     * 获取企业授权信息
     * @param $auth_corpId
     * @param $PermanentCode
     * @return \GetAuthInfoRsp
     */
    public function getAuthInfo($auth_corpId,$PermanentCode){
        $service = new \ServiceCorpAPI();
        $authInfo = $service->GetAuthInfo($auth_corpId,$PermanentCode);
        return $authInfo;
    }
    /**
     * 获取授权企业的应用凭证
     * @param $get_suite_token
     * @param $PermanentCode
     * @param $corpid
     * @return bool|mixed
     */
    public function get_access_token($get_suite_token,$PermanentCode,$corpid){
        $url="https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=".$get_suite_token;
        $params=["permanent_code"=>$PermanentCode,"auth_corpid"=>$corpid];
        $result = curl_post($url,$params);
        $data = json_decode($result);
        if (property_exists($data,'access_token')){
            $expires_in = $data->expires_in;//过期时间
            $key = $corpid;//企业id
            cache($key,json_encode($data->access_token),$expires_in);
            return $data->access_token;
        }else{
            return false;
        }
    }
    /**
     * 将接收到的suite_tikect存入缓存中，无论缓存是否失效
     * @param $caheValue
     * @return bool
     * @throws WorkSuiteTicketException
     */
    private function saveToCache($caheValue){
        $key =  $caheValue['SuiteId'] ;
        $value = json_encode($caheValue);
        $expire_in = config('setting.suite_expire_in');
           $result =  cache($key,$value,$expire_in);
            if (!$result){
                throw new WorkSuiteTicketException();
            }
        return $key;
    }

    /**
     * 将xml转化成数组
     * @param $xml
     * @return mixed
     */
    static public  function Xml2Array($xml)
    {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;
    }

    /**
     * 获取accessToken
     * @param $suitId
     * @return bool
     */
    public function getAccessToken($suitId,$Secret){
        $data  = cache($suitId);
        if ($data  != null ){
            $info = json_decode($data);
            $suite_ticket = $info->SuiteTicket;
            $result = $this->get_suite_token($suitId,$Secret,$suite_ticket);
            return $result;
        }else{
            return false;
        }
    }
    /**
     * 获取第三方应用凭证
     * @param $suitId
     * @param $Secret
     * @param $suite_ticket
     * @return mixed
     */
    public  function get_suite_token($suitId,$Secret,$suite_ticket){
        $name = 'suit_'.$suitId;
        if (cache($name)){
            $data = cache($name);
            return $data;
        }
        $url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";
        $params=[
            "suite_id" => $suitId,
            "suite_secret" => $Secret,
            "suite_ticket" => $suite_ticket,
        ];
        $result = curl_post($url,$params);
        $data = json_decode($result);
        $time = $data->expires_in - 60;//提前过期
        cache($name,$data->suite_access_token,$time);
        return $data->suite_access_token;
    }

    /**
     * 企业变更通知
     * @param $data
     * @return int
     */
    private function receiveAuthNotify($data){
        $countInfo = WorkModel::getCountInfo($data['AuthCorpId']);
        switch ($data['ChangeType']){
            case 'create_user'://创建人员
                if (!(isset($data['Mobile']) && isset($data['Email']))){
                    $result =  WorkUser::getUser($countInfo->t_id,$data['UserID']);
                    if (empty($result)){
                        list($info, $data) = $this->getUserInsertData($data, $info=[]);
                        WorkUser::createUser($countInfo->t_id,$info);
                    }
                }
                break;
            case 'update_user';//更新人员
                    $workUser = WorkUser::getUser($countInfo->t_id,$data['UserID']);
                    $info = $this->getUserUpdateData($data,$workUser,$info=[]);
                    $info['id'] = $workUser->id;
                    WorkUser::updateUser($countInfo->t_id,$info);
                break;
            case 'delete_user';//删除人员
                    $user[0] = $data['UserID'];
                    $str = WorkUser::deleteUser($countInfo->t_id,$user);
                break;
            case 'create_party';//创建部门
                    $result =  WorkDepartment::getDepartment($countInfo->t_id,$data['Id']);
                    if (empty($result)){
                        $info = $this->getDepartmentAddData($data,$info=[]);
                        $str = ThirdApp::addUserDepartment($countInfo->t_id,$info);
                    }
                break;
            case 'update_party';//更新部门
                    $d_id = $data['Id'];
                    $department = WorkDepartment::getDepartment($countInfo->t_id,$data['Id']);
                    $data = $this->getDepartmentUpdateData($data, $department,$info=[]);
                    $str = WorkDepartment::updateDepartment($countInfo->t_id,$d_id,$data);
                break;
            case 'delete_party';//删除部门
                    $d_id = $data['Id'];
                    $str =  WorkDepartment::deleteDepartment($countInfo->t_id,$d_id);
                break;
            case 'update_tag';//跟新标签

                break;
        }
        return $str;
    }

    /**
     * 取消授权
     * @param $data
     * @return int
     */
    private function deleteApply($data){
        $info = \app\api\model\Work::getCountInfo($data['AuthCorpId']);
        $result = WorkAgent::deleteAgents($info->id,$data['SuiteId']);
        return $result;
    }

    /**
     * 添加用户数据
     * @param $data
     * @param $info
     * @return array
     */
    private function getUserInsertData($data, $info): array
    {
        $info['name'] = $data['Name'];
        $info['alias'] = isset($data['Alias']) ? $data['Alias'] : $data['Name'];
        $info['avatar'] = $data['Avatar'];
        $info['userId'] = $data['UserID'];
        $info['gender'] = $data['Gender'];
        $info['bind_phone'] = $data['Mobile'];
        $info['phone'] = $data['Mobile'];
        $info['position'] = isset($data['Position']) ? $data['Position'] : '无';
        $info['d_id'] = explode(',', $data['Department']);
        $info['isleader'] = explode(',', $data['IsLeaderInDept']);
        return array($info, $data);
    }

    /**
     * 更新数据
     * @param $data
     * @param WorkUser $workUser
     * @param $info
     * @return mixed
     */
    private function getUserUpdateData($data,WorkUser $workUser,$info) {
        $info['userId'] = $data['UserID'];
        $info['name'] = isset($data['Name']) ? $data['Name'] : $workUser->name;
        $info['alias'] = isset($data['Alias']) ? $data['Alias'] : $workUser->alias;
        $info['avatar'] = isset($data['Avatar']) ? $data['Avatar'] : $workUser->avatar;
        $info['gender'] = isset($data['Gender']) ? $data['Gender'] : $workUser->gender;
        $info['bind_phone'] = isset($data['Mobile']) ? $data['Mobile'] : $workUser->bind_phone;
        $info['position'] = isset($data['Position']) ? $data['Position'] : $workUser->position;
        if (isset($data['Department'])){
            $info['d_id'] = explode(',', $data['Department']);
        }
        if (isset($data['IsLeaderInDept'])){
            $info['isleader'] = explode(',', $data['IsLeaderInDept']);
        }
        return $info;
    }

    /**
     * 准备部门添加数据
     * @param $data
     * @param $info
     * @return mixed
     */
    private function getDepartmentAddData($data,$info){
        $info['d_id'] = $data['Id'];
        $info['name'] = $data['Name'];
        $info['parentid'] = $data['ParentId'];
        $info['order'] = $data['Order'];
        return $info;
    }

    /**
     * 准备部门更新数据
     * @param $data
     * @param WorkDepartment $department
     * @param $info
     * @return mixed
     */
    private function getDepartmentUpdateData($data,WorkDepartment $department,$info){
        $info['d_id'] = $data['Id'];
        $info['name'] = isset($data['Name']) ? $data['Name'] : $department->name;
        $info['parentid'] = isset($data['ParentId']) ? $data['ParentId'] : $department->parentid;
        $info['order'] = isset($data['Order']) ? $data['Order'] : $department->order;
        return $info;
    }
}